home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / utils / chkpt10.zip / CHKPTBL.C next >
Text File  |  1996-04-05  |  28KB  |  868 lines

  1. #ifndef __TINY__
  2. #error Must be compiled in tiny model
  3. #endif
  4.  
  5. /* *********************************************************************** */
  6. /*   This program compares the root sector  (that is partition  table for  */
  7. /*  hard disks and boot sector for floppy disks)  and, optionally (in the  */
  8. /*  case of an hard disk), the boot sector with data stored in a supplied  */
  9. /*  file.                                                                  */
  10. /*   The data files could be generated always with this same program.      */
  11. /*   A lot of options allow a full control of program,  but has to be re-  */
  12. /*  membered that such a program works at an intimate level with the com-  */
  13. /*  computers hardware and so its use must be very careful. No warranties  */
  14. /*  are given and the author could not be claimed responsible for damages  */
  15. /*  produced by the use of the program.                                    */
  16. /*   One possible use of this program is to save root and boot sector  of  */
  17. /*  the hard disk and check them every boot  (inserting a command in  the  */
  18. /*  autoexec.bat file) to reveal undesired changes (maybe a virus) and e-  */
  19. /*  ventually, with maximum care, restore the original data.               */
  20. /*                                                                         */
  21. /*   syntax:                                                               */
  22. /*   CHKPTBL [switches] <file-name>                                        */
  23. /*     <file-name> is the data file to compare root sector with.           */
  24. /*           If no extension is present extension .TBL is added, if a di-  */
  25. /*          rectory name is supplied (ending with '\')  the default  name  */
  26. /*          PARTTBL.TBL is used. If no name is supplied no check is made.  */
  27. /*                                                                         */
  28. /*     switches:                                                           */
  29. /*                                                                         */
  30. /*     /H[1..Number of physical hard drive - default 1] selects the  phy-  */
  31. /*          sical hard drive subsequent commands refer to.                 */
  32. /*           For default hard drive 1 is taken.                            */
  33. /*     /F[1..Number of physical floppy drive - default 1]selects the phy-  */
  34. /*          sical floppy drive subsequent commands refer to.               */
  35. /*           If /F with no number is specified physical floppy 1 is taken  */
  36. /*     /S    Stop if differences are found between data stored in the fi-  */
  37. /*          le and actual root (boot) sector.                              */
  38. /*     /C    If differences are found between data stored in the file and  */
  39. /*          actual root (boot) sector, correct them restoring the data in  */
  40. /*          file.                                                          */
  41. /*     /B[+|-] Set the "Check boot sector too" option true(/B+) or  false  */
  42. /*          (/B-).  If this switch is not specified the option is  false,  */
  43. /*          if only /B is specified the option is set to true.             */
  44. /*     /W[+]<file-name> Store drive-data to <file-name> (ext. and name as  */
  45. /*          for reference file).   If the file already exists, if  /W+ is  */
  46. /*          specified the file is overwritten, otherwise nothing is done.  */
  47. /*           If the "Check boot sector too" option  is actually true  and  */
  48. /*          the actually selected drive is an hard whose partition number  */
  49. /*          one is a dos bootable partition even the boot sector is saved  */
  50. /*          (for a total of 1024 bytes),otherwise only the root sector is  */
  51. /*          written to the file.                                           */
  52. /*                                                                         */
  53. /*   example:                                                              */
  54. /*   CHKPTBL /Wfile1 /B /H2 /Wfile2/F/Wfile3 /H/Wfile4 C:\DOS\             */
  55. /*     Actions:                                                            */
  56. /*     The root sector of hard drive 1 is written to file1, the root sec-  */
  57. /*    tor of hard drive 2 (which is generally a not dos-bootable disk) is  */
  58. /*    written to file2, the root sector (which is the boot sector) of the  */
  59. /*    floppy drive 1 (usually a:) is written to file3 and the root sector  */
  60. /*    and the first partition's boot sector (if it's a DOS-bootable  par-  */
  61. /*    tition) of the hard drive 1 are written to file4 and both are  com-  */
  62. /*    pared with the file C:\DOS\PARTTBL.TBL.                              */
  63. /*                                                                         */
  64. /*   (c) 1996 by Luigi Mancinelli                                          */
  65. /*   manci@alpha.science.unitn.it                                          */
  66. /*                                                                         */
  67. /*   Note: If the program has to be recompiled, the tiny model has  to be  */
  68. /*  used and the resulting .exe has to be converted in .com (with the DOS  */
  69. /*  utility EXE2BIN for example) or the program doesn't work.              */
  70. /*                                                                         */
  71. /* *********************************************************************** */
  72.  
  73. #define NULL 0
  74. #if __STDC__
  75. #define _Cdecl
  76. #else
  77. #define _Cdecl cdecl
  78. #endif
  79.  
  80. void _Cdecl __int__(int interruptnum);
  81. void __emit__();
  82. /* extern unsigned _Cdecl _psp; */
  83.  
  84. #define SEG_FP(fp)  (((unsigned int *) (&(fp)))[1])
  85. #define OFS_FP(fp)  ((unsigned int) (fp))
  86.  
  87.  
  88.  
  89.  
  90. #include <dir.h>
  91.  
  92. #define _toupper(c)     ((c)&0xDF)
  93.  
  94. #define putchar(c) (_DL=c,_AH=02,__int__(0x21))
  95.  
  96. #define putbackslash() (_DL='\\',_AH=02,__int__(0x21))
  97.  
  98. void putstring(char *p)
  99. {   unsigned int i=0;
  100.     if (p!=NULL)
  101.        while (p[i]!=0) putchar(p[i++]);
  102. }
  103.  
  104.   char *HexDig="0123456789ABCDEF";
  105.  
  106. void puthexbyte(unsigned char ch)
  107. {
  108.    putchar(HexDig[ch>>4]);
  109.    putchar(HexDig[ch&0xF]);
  110. }
  111.  
  112. void newline(void)
  113. {  putchar('\r'); putchar('\n'); }
  114.  
  115. typedef unsigned char byte;
  116. typedef unsigned int word;
  117.  
  118. word DOSFileError=0;
  119.  
  120. word FCreate(const char far * filename, byte fmode)
  121. {
  122.   word SaveDS;
  123.   SaveDS=_DS;
  124.   _CX=fmode;
  125.   _AH=0x3C;
  126.   _DS=SEG_FP(filename);
  127.   _DX=OFS_FP(filename);
  128.   __int__(0x21);
  129.   _DS=SaveDS;
  130.   __emit__(0xBB,0x00,0x00,0x73,0x02,0x87,0xC3);
  131.     /* MOV BX,0 - JNC L1 - XCHG AX,BX - L1: */
  132.     /* IF CY THEN _BX=_AX _AX=0 ELSE _BX=0 */
  133.   DOSFileError=_BX;
  134.   return _AX;
  135. }
  136.  
  137. word FOpen(const char far * filename, byte fmode)
  138. {
  139.   word SaveDS;
  140.   SaveDS=_DS;
  141.   _AH=0x3D; _AL=fmode;
  142.   _DS=SEG_FP(filename);
  143.   _DX=OFS_FP(filename);
  144.   __int__(0x21);
  145.   _DS=SaveDS;
  146.   __emit__(0xBB,0x00,0x00,0x73,0x02,0x87,0xC3);
  147.     /* MOV BX,0 - JNC L1 - XCHG AX,BX - L1: */
  148.     /* IF CY THEN _BX=_AX _AX=0 ELSE _BX=0 */
  149.   DOSFileError=_BX;
  150.   return _AX;
  151. }
  152.  
  153. int FRead(word handle, byte far * buffer,
  154.           word BytesToRead, word far *BytesRead)
  155. {
  156.   word SaveDS;
  157.   SaveDS=_DS;
  158.   _AH=0x3F;
  159.   _BX=handle;
  160.   _DS=SEG_FP(buffer);
  161.   _DX=OFS_FP(buffer);
  162.   _CX=BytesToRead;
  163.   __int__(0x21);
  164.   _DS=SaveDS;
  165.   __emit__(0xBB,0x00,0x00,0x73,0x02,0x87,0xC3);
  166.     /* MOV BX,0 - JNC L1 - XCHG AX,BX - L1: */
  167.     /* IF CY THEN _BX=_AX _AX=0 ELSE _BX=0 */
  168.   DOSFileError=_BX;
  169.   *BytesRead=_AX;
  170.   if (DOSFileError) return -1;
  171.   else if (_AX==0) return 1;
  172.   else if (_AX<BytesToRead) return 2;
  173.   else return 0;
  174. }
  175.  
  176. int FWrite(word handle, byte far * buffer,
  177.           word BytesToWrite, word far *BytesWritten)
  178. {
  179.   word SaveDS;
  180.   SaveDS=_DS;
  181.   _AH=0x40;
  182.   _BX=handle;
  183.   _DS=SEG_FP(buffer);
  184.   _DX=OFS_FP(buffer);
  185.   _CX=BytesToWrite;
  186.   __int__(0x21);
  187.   _DS=SaveDS;
  188.   __emit__(0xBB,0x00,0x00,0x73,0x02,0x87,0xC3);
  189.     /* MOV BX,0 - JNC L1 - XCHG AX,BX - L1: */
  190.     /* IF CY THEN _BX=_AX _AX=0 ELSE _BX=0 */
  191.   DOSFileError=_BX;
  192.   *BytesWritten=_AX;
  193.   if (DOSFileError) return -1;
  194.   else if (_AX==0) return 1;
  195.   else if (_AX<BytesToWrite) return 2;
  196.   else return 0;
  197. }
  198.  
  199.  
  200. int FClose(word handle)
  201. {
  202.   _AH=0x3E;
  203.   _BX=handle;
  204.   __int__(0x21);
  205.   __emit__(0xBB,0x00,0x00,0x73,0x02,0x87,0xC3);
  206.     /* MOV BX,0 - JNC L1 - XCHG AX,BX - L1: */
  207.     /* IF CY THEN _BX=_AX _AX=0 ELSE _BX=0 */
  208.   DOSFileError=_BX;
  209.   if (_BX) return -1; else return 0;
  210. }
  211.  
  212.  
  213. #define B_READ 0x2
  214. #define B_WRITE 0x3
  215. #define B_VERIFY 0x4
  216.  
  217. /* biosdisk */
  218. int ResetDrives(byte drive)
  219. {
  220.   _AH=0;
  221.   _DL=drive /* 0x80 */;
  222.   __int__(0x13);
  223.     /* __emit__(0x73,0x02,0xB4,0x00);  */
  224.     /* JNC L1 - MOV AH,0 - L1:         */
  225.     /* IF CY THEN _AH=ERROR ELSE _AH=0 */
  226.   return _AH;
  227. }
  228.  
  229. int _HardDrives(void)
  230. {
  231.    _AH=0x8;
  232.    _DL=0x80;
  233.    __int__(0x13);
  234.    return _DL;
  235. }
  236.  
  237. int _FloppyDrives(void)
  238. {
  239.    _AH=0x8;
  240.    _DL=0;
  241.    __int__(0x13);
  242.    return _DL;
  243. }
  244.  
  245. int _BiosDiskLL(byte func, byte drive, byte head, word tracksect,
  246.                 void far * BuffOfs)
  247. {
  248.   _ES=((word *) (&BuffOfs))[1];
  249.   _DL=drive /* 0x80 */;
  250.   _CX=tracksect; /*  _CH=track;  _CL=sectnum; */
  251.   _DH=head;
  252.   _BX=*((word *) (&BuffOfs));
  253.   _AH=func;
  254.   _AL=1;
  255.   __int__(0x13);
  256.   /*  __emit__(0x73, 0x02, 0xB4, 0x00); */
  257.   /*    JNC L1 -- MOV AH,0 -- L1:       */
  258.   return _AH;
  259. }
  260.  
  261. int ReadSectorLL(byte drive, byte head, word tracksect,
  262.                  void far * BuffOfs)
  263. {
  264.   int i,done,Err;
  265.   for (i=done=0; i<3; i++) {
  266.      if((Err=_BiosDiskLL(B_READ,drive,head,tracksect,BuffOfs))==0)
  267.         { done=1; break; }
  268.      ResetDrives(drive);
  269.   }
  270.   if(done==0) return Err;
  271.   else return 0;
  272. }
  273.  
  274. int WriteSectorLL(byte drive, byte head, word tracksect,
  275.                   void far * BuffOfs)
  276. {
  277.   int i,done,Err;
  278.   for (i=done=0; i<3; i++) {
  279.      if((Err=_BiosDiskLL(B_WRITE,drive,head,tracksect,BuffOfs))==0)
  280.         { done=1; break; }
  281.      ResetDrives(drive);
  282.   }
  283.   if(done==0) return Err;
  284.   else return _BiosDiskLL(B_VERIFY,drive,head,tracksect,BuffOfs);
  285. }
  286.  
  287. char *stradd(char *Dest, const char *ToAdd)
  288. {
  289.    unsigned int i=0,j=0,ilim,jlim;
  290.    /*
  291.    unsigned int j=0;
  292.    unsigned int ilim,jlim;
  293.    */
  294.    ilim=(unsigned int) Dest;
  295.    ilim=65535-ilim;
  296.    jlim=(unsigned int) ToAdd;
  297.    jlim=65535-jlim;
  298.    while ((i<=ilim)&&(Dest[i]!=0)) i++;
  299.    while ((i<=ilim)&&(j<=jlim)&&(ToAdd[j]!=0)) Dest[i++]=ToAdd[j++];
  300.    if(i<=ilim) Dest[i]=0;
  301.    return Dest;
  302. }
  303.  
  304. #define IsInSet(ch,Set) ((Set[ch>>3]>>(ch&7))&1)
  305.  
  306. /* errors (<0 ) */
  307. #define FNInvalidChar -1
  308. #define FNInvalidDrive -2
  309. #define FNInvalidPath -4
  310. #define FNBlankUnacceptable -8
  311. #define FNPointUnacceptable -16
  312. #define FNInvalidNetName -32
  313. #define FNPathToLong -64
  314. #define FNPathNameToLong -128
  315.  
  316. /* informations */
  317. #define FNNetName 1
  318. #define FNNoName 2
  319. #define FNJollyInName  4
  320. #define FNJollyInExt 8
  321. #define FNJolly 12
  322. #define FNExtPres 16
  323. #define FNNoNullExt 32
  324. #define FNIsPathName 64
  325. #define FNBlankPresent 128
  326. #define FNJollyInPath 256
  327.  
  328. /* parsing options */
  329. #define FNStopOnInvalidChar 1
  330. #define FNAcceptJollyInPath 2
  331. #define FNAcceptBlank 4
  332. #define FNCheckDevName 8
  333. #define FNTerminChar 16
  334.  
  335. char FlNmSetOfUnaccChars[32]={
  336.       0xFF,0xFF,0xFF,0xFF,0x04,0xD8,0x00,0x7C,
  337.       0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x10,
  338.       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  339.       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  340.         /*  FlPathNmUnaccChs :Set Of Char=
  341.               [#0..#31,'"','+',',','.','/',
  342.               ':',';','<','=','>','[','\',']','|'];
  343.         */
  344.  
  345. int TrueName(int *Drive, char *pathname, char**name, char *src,
  346.              int *pos, int Param)
  347. {
  348. #define STARINNAME 2
  349. #define STARINEXT 4
  350. #define DEVNAME 8
  351.    int i,j,strtp,strtn,strte,l;
  352.    char Fnd;
  353.    char ch1,ch2;
  354.  
  355.    char TermChar=0;
  356.    int Error=0;
  357. #define ErrorANDReset (~((unsigned int) FNJollyInName | FNJollyInExt | \
  358.                         FNExtPres | FNNoNullExt))
  359.    *Drive=0;
  360.    strte=i=j=0;
  361.    Fnd=0;
  362.    /* adjust src pointer */
  363.    src=&(src[*pos]);  /* caveat programmer: (*pos)<strlen(src) */
  364.    if((Param & FNTerminChar)!=0)
  365.      { TermChar=Param>>8; /* printf("\a\a(Term on %d)\n",TermChar); */ }
  366.    *name=&(pathname[0]);
  367.    if(((ch1=(pathname[0]=src[0]))==0)||(ch1==TermChar)) return pathname[0]=0;
  368.    if(((ch2=(pathname[1]=src[1]))==0)||(ch2==TermChar)) {
  369.       if(ch2!=0) pathname[1]=0;
  370.       if(ch1=='.') {Error=FNPointUnacceptable; pathname[0]=0;}
  371.       else if(ch1=='\\') {*name=&(pathname[1]); (*pos)++; Error|= FNNoName;}
  372.       else if(IsInSet(ch1,FlNmSetOfUnaccChars)==0) (*pos)++;
  373.       else { Error=FNInvalidChar; pathname[0]=0; }
  374.       return Error;
  375.    }
  376.    if(ch2==':') {
  377.       if((((*Drive)=_toupper(ch1)-65)<0)||((*Drive)>=setdisk(getdisk())) )
  378.          return FNInvalidDrive;  /* invalid Drive specification */
  379.       else {i=j=strtn=strtp=2;}
  380.    }
  381.    else if((ch1=='\\')&&(ch2=='\\')) {
  382.            /* machine specification found */
  383.            i=j=strtn=2; strtp=-1;
  384.            Error|=FNNetName;
  385.    }
  386.    else strtn=strtp=0;
  387.    while ((Error>=0)&&(Fnd!=-1)&&
  388.           ((ch1=(pathname[i++]=src[j++]))!=0)&&(ch1!=TermChar)) {
  389.       if((i>92)||(((Error & FNNetName==0))&&(i>80))) Error=FNPathNameToLong;
  390.       else
  391.       switch (ch1) {
  392.       case '.' :if(strte!=0)
  393.                    /* not valid point in this pos. */
  394.                    Error=FNPointUnacceptable;
  395.                 else if((i-1)>strtn) {
  396.                    if(src[j]=='\\') i--;
  397.                    else {Fnd=0; strte=i; Error|=FNExtPres; }
  398.                 }
  399.                 else if(strtp==-1) Error=FNInvalidNetName;
  400.                               /* not valid as a machine specification */
  401.                 else if((ch2=src[j])==0) Error=FNPointUnacceptable;
  402.                 else if(ch2=='\\') {
  403.                    if((strtn>strtp)|| ((i>3)&&(pathname[i-2]=='\\')
  404.                       &&(pathname[i-3]=='.')) ) { i--; if(i==strtn)j++; }
  405.                 }
  406.                 else if((ch2=='.')&&(src[j+1]=='\\')) {
  407.                     /*  ..\ */
  408.                    if((i>=2)&&((i-2)==strtp)&&(pathname[i-2]=='\\'))
  409.                       Error=FNInvalidPath;
  410.                    else if((i-1)==strtp){
  411.                       pathname[i++]='.'; pathname[i++]='\\';
  412.                       j+=2; strtn=strtp=i;
  413.                    }
  414.                    else {
  415.                       i-=3;
  416.                       while((i>=strtp)&&(pathname[i]!='\\')) i--;
  417.                       if(Param & FNAcceptJollyInPath) {
  418.                          Error&= ~FNJollyInPath;
  419.                          for(l=strtp; l<i; l++)
  420.                             if((pathname[l]=='?')||(pathname[l]=='*') )
  421.                                Error|= FNJollyInPath;
  422.                       }
  423.                       j+=2; strtn=++i;
  424.                    }
  425.                 }
  426.                 else Error=FNPointUnacceptable;
  427.                 break;
  428.       case '\\':if(((i-1)==strtn)&&(strtn!=strtp)) Error=FNInvalidChar;
  429.                 else {
  430.                    if(strtp==-1) strtp=i;
  431.                    else {
  432.                       if(Error & FNJolly) {
  433.                          if ((Param & FNAcceptJollyInPath)==0)
  434.                             Error=FNInvalidPath;
  435.                          else Error|= FNJollyInPath;
  436.                       }
  437.                    }
  438.                    if((i-strtp)>66) Error=FNPathToLong;
  439.                    else {
  440.                       Error&= ErrorANDReset;
  441.                       strtn=i; strte=0; Fnd=0;
  442.                    }
  443.                 }
  444.                 break;
  445.       case '?' :
  446.       case '*' :if(strtp==-1) Error=FNInvalidNetName;
  447.                 else if(Fnd|| (((strte>0)&&((i-strte)>3))||
  448.                               ((strte==0)&&((i-strtn)>8)) ) ) i--;
  449.                 else {
  450.                    if(strte==0) Error|= FNJollyInName;
  451.                    else Error|= FNNoNullExt | FNJollyInExt;
  452.                    if(ch1=='*') Fnd=1;
  453.                    /* Once it's true it doesn't become false until
  454.                       '\' or '.' is found */
  455.                 }
  456.                 break;
  457.       default  :/* if ch1 in invalid chars ... stop */
  458.                 if ((IsInSet(ch1,FlNmSetOfUnaccChars)!=0)||
  459.                     ((ch1==' ')&&((Param & FNAcceptBlank)==0)) ) {
  460.                    if(Param & FNStopOnInvalidChar) Fnd=-1;
  461.                    else Error=FNInvalidChar;
  462.                 }
  463.                 else if((ch1==' ')&&((i-1)==strtn))Error=FNBlankUnacceptable;
  464.                 else if(Fnd|| (((strte>0)&&((i-strte)>3))||
  465.                               ((strte==0)&&((i-strtn)>8)) ) ) i--;
  466.                 else {
  467.                    if(strte>0) Error|= FNNoNullExt;
  468.                    if(ch1==' ') Error|= FNBlankPresent;
  469.                 }
  470.       }
  471.    }
  472.    if(Error>=0) {
  473.       if(strtp==-1) /* machine name */ ;
  474.       (*pos)+=j-1;
  475.       if(ch1!=0)pathname[i-1]=0;
  476.       *name=&(pathname[strtn]);
  477.       if(pathname[strtn]==0) Error|= FNNoName;
  478.    } else { (*pos)+=j-1; pathname[i-1]=0; }
  479.    return Error;
  480. #undef ErrorANDReset
  481. }
  482.  
  483. #define CR 0x0D
  484.  
  485.  
  486. /* *************************** */
  487. byte *CmdStr=(byte *) 0x80;
  488. int pos=1;
  489.  
  490. void SkipBlanks(void) {
  491.    while ((CmdStr[pos]==' ')||(CmdStr[pos]==9)) pos++;
  492. }
  493.  
  494.  
  495. #define INVALIDSWITCH -1
  496. #define INVALIDDRIVE -2
  497. #define INVALIDPATH -3
  498. #define PATHTOLONG -4
  499. #define PATHNAMETOLONG -5
  500. #define UNACCEPTABLECHAR -6
  501. #define UNTERMINATEDSTRING -7
  502. #define JOLLYUNACCEPTED -8
  503.  
  504. #define ROOTUNREADABLE -10
  505.  
  506. #define EE_UNREADABLE 1
  507. #define EE_UNWRITABLE 2
  508. #define EE_NOTCHECKED 4
  509. #define EE_BOOTNOTCHECKED 8
  510. #define EE_ERRORINREADING 16
  511. #define EE_ERRORINWRITING 32
  512. #define EE_CORRECTED 128
  513.  
  514.  
  515. char *ErrMess[8]={" Invalid switch or syntax error",
  516.                   " Invalid drive"," Invalid path",
  517.                   " - path to long"," - path name to long",
  518.                   " unacceptable char"," expected -- Unterminated string",
  519.                   " -- Jolly unaccepted"};
  520.  
  521.  
  522. #define READ 1
  523. #define WRITE 0
  524. #define BOOT 1
  525. #define ROOT 0
  526. char *UnableTo="\7\7Unable to ";
  527. char *Read="read ";
  528. char *Write="write ";
  529. char *Sector="oot sector\r\n";
  530. int putUnableTo(int rd, int bt)
  531. {
  532.    putstring(UnableTo);
  533.    if(rd==READ) putstring(Read); else putstring(Write);
  534.    if(bt==BOOT) putchar('b'); else putchar('r');
  535.    putstring(Sector);
  536. }
  537.  
  538.  
  539.  
  540. char *SkipExisting="Skip existing";
  541. char *MaybeDiskFull="Unable to write data (maybe disk-full) to";
  542. char *NotGoodFile="Not good";
  543. char *File=" file ";
  544. #define OPENING 0
  545. #define READING 1
  546. #define CLOSING 2
  547. #define CREATING 3
  548. #define WRITING 4
  549. char *DosErrWhile[5]={"opening","reading","closing","creating","writing to"};
  550.  
  551. int putDOSError(int ErrWhile, char * FileName)
  552. {
  553.     putstring("DOS error "); puthexbyte(DOSFileError); putstring(" in ");
  554.     putstring(DosErrWhile[ErrWhile]); putstring(File);
  555.     putstring(FileName);
  556.     newline();
  557. }
  558.  
  559. char *NotEquals="oot Sector and ref. file are not equal\r\n\7\7\7";
  560.  
  561. byte HDrives;
  562. byte FDrives;
  563.  
  564. char FlName[92];
  565. char Opened[92];
  566. char *Name;
  567. word IHandle=0;
  568. word OHandle=0;
  569. byte OverWrite=0;
  570.  
  571. char SwitchChar='/';
  572. int Error=0;
  573.  
  574. int FnError=0;
  575. int FnParam=0;
  576.  
  577. byte ExitError=0;
  578.  
  579. char AutoCorrect=0;
  580. char StopOnError=0;
  581. byte Drive=0x80;
  582. byte Partition=0;
  583. int PartOfs=0x1BE;
  584. byte ReadRoot=1;
  585. byte BootToo=0;
  586.  
  587. byte RootSect[1024];
  588. byte Buffer[1024];
  589. word RW_size=512;
  590.  
  591. word i;
  592. char Ch,c;
  593.  
  594. int BootPartition(byte *Root)
  595. {
  596.    byte System;
  597.    PartOfs=0x1BE+16*Partition;
  598.    System=Root[PartOfs+04];
  599.    return (Root[PartOfs]==0x80)&&
  600.           ((System==01)||(System==04)||(System==06));
  601. }
  602.  
  603. int ReadPTable(void)
  604. {
  605.    ResetDrives(Drive);
  606.    if(ReadRoot==1) {
  607.       if(ReadSectorLL(Drive,0,1,(void far *) (RootSect))==0) {
  608.          ReadRoot=0;
  609.          ExitError&=~EE_UNREADABLE;
  610.          if(BootToo && (Drive & 0x80) && BootPartition(RootSect)) {
  611.             if(ReadSectorLL(Drive,RootSect[PartOfs+1],
  612.                             *((word *)&(RootSect[PartOfs+2])),
  613.                             (void far *) &(RootSect[512]))==0) {
  614.                RW_size=1024;
  615.                ExitError&=~EE_BOOTNOTCHECKED;
  616.             }
  617.             else {
  618.                ReadRoot=3;
  619.                putUnableTo(READ,BOOT);
  620.                ExitError|=~EE_UNREADABLE;
  621.             }
  622.          }
  623.          else {
  624.             RW_size=512;
  625.             if(BootToo && (Drive & 0x80)) ExitError|=EE_BOOTNOTCHECKED;
  626.          }
  627.       }
  628.       else {
  629.          ReadRoot=2;
  630.          putUnableTo(READ,ROOT);
  631.          ExitError|=EE_UNREADABLE;
  632.       }
  633.    }
  634.    return ReadRoot;
  635. }
  636.  
  637. int WritePTable(void)
  638. {
  639.    ResetDrives(Drive);
  640.    if(WriteSectorLL(Drive,0,1,(void far *) (Buffer))==0) {
  641.       if(BootToo && (Drive & 0x80) && BootPartition(Buffer)) {
  642.          if(WriteSectorLL(Drive,Buffer[PartOfs+1],
  643.                             *((word *)&(Buffer[PartOfs+2])),
  644.                             (void far *) &(Buffer[512]))!=0) {
  645.             putUnableTo(WRITE,BOOT);
  646.             ExitError|=~EE_UNWRITABLE;
  647.          }
  648.       }
  649.       else if(BootToo && (Drive & 0x80)) ExitError=EE_BOOTNOTCHECKED;
  650.    }
  651.    else {
  652.       putUnableTo(WRITE,ROOT);
  653.       ExitError|=EE_UNWRITABLE;
  654.    }
  655.    return ((ExitError & EE_UNWRITABLE)!=0);
  656. }
  657.  
  658. int IsGoodSeparator(unsigned char Ch)
  659. {
  660.    return ((Ch==' ')||(Ch==9)||(Ch==CR)||(Ch==SwitchChar));
  661. }
  662.  
  663. int CheckIfInvalid(char c)
  664. {
  665.    if(!IsGoodSeparator(c)) {
  666.       putchar('/'); putchar(Ch); Error=INVALIDSWITCH;
  667.    }
  668.    return Error==INVALIDSWITCH;
  669. }
  670.  
  671. int GetFileName(void)
  672. {
  673.    int Drive;
  674.    char FndCh;
  675.    FnParam=FNTerminChar|(((word) CR)<<8)|FNStopOnInvalidChar;
  676.    if ((Ch=='"')||(Ch=='[')) {
  677.       pos++; if (Ch=='"') FndCh='"'; else FndCh=']';
  678.       FnParam|=FNAcceptBlank;
  679.    } else FndCh=0;
  680.    FnError=TrueName((int *)&i,FlName,&Name,CmdStr,&pos,FnParam);
  681.    if(FnError<0) {
  682.       if(FnError==FNInvalidDrive) Error=INVALIDDRIVE;
  683.       else if(FnError==FNInvalidPath) Error=INVALIDPATH;
  684.       else if(FnError==FNPathToLong) Error=PATHTOLONG;
  685.       else if(FnError==FNPathNameToLong) Error=PATHNAMETOLONG;
  686.       else Error=UNACCEPTABLECHAR;
  687.    }
  688.    else if(FndCh!=0){
  689.       if(CmdStr[pos]==FndCh) pos++;
  690.       else if(CmdStr[pos]=='\r') Error=UNTERMINATEDSTRING;
  691.       else Error=UNACCEPTABLECHAR;
  692.    }
  693.    else if(!IsGoodSeparator(CmdStr[pos])) Error=UNACCEPTABLECHAR;
  694.    else if(FnError&FNJolly) Error=JOLLYUNACCEPTED;
  695.    if(Error==0) {
  696.       if(FnError & FNNoName) stradd(FlName,"PARTTBL.TBL");
  697.       else if((FnError & FNExtPres)==0) stradd(FlName,".TBL");
  698.    }
  699.    return Error;
  700. }
  701.  
  702. int cdecl main() {
  703. /*
  704. unsigned int DS=((unsigned long)((char far *)(&CmdStr)))>>16;
  705. if(DS==_psp) { */
  706.    i=CmdStr[0];
  707.    if(CmdStr[i+1]!=CR) CmdStr[i+1]=CR;
  708.  
  709.    HDrives=_HardDrives();
  710.    FDrives=_FloppyDrives();
  711.  
  712.    /*
  713.    putchar(HDrives+0x30); putstring(" hard disks and ");
  714.    putchar(FDrives+0x30); putstring(" floppy disks\r\n");
  715.    */
  716.  
  717.    SkipBlanks();
  718.    while ((Error==0)&&((Ch=CmdStr[pos])!=0xD)) {
  719.       if (Ch==SwitchChar) {
  720.          switch (Ch=_toupper(CmdStr[++pos])) {
  721.          case 'S': StopOnError=1;  CheckIfInvalid(CmdStr[++pos]);  break;
  722.          case 'C': AutoCorrect=1;  CheckIfInvalid(CmdStr[++pos]);  break;
  723.          case 'B': if(((c=CmdStr[++pos])=='-')||(c=='+')) {
  724.                       pos++;
  725.                       BootToo=(c=='+');
  726.                    }
  727.                    else BootToo=1;
  728.                    if((CheckIfInvalid(CmdStr[pos]))&&(c!=CmdStr[pos]))
  729.                       putchar(c);
  730.                    ReadRoot=1;
  731.                    break;
  732.          case 'F':
  733.          case 'H': i=Drive;
  734.                    if(IsGoodSeparator(c=CmdStr[++pos])) {
  735.                       Drive=0; if(Ch=='H') Drive|=0x80;
  736.                    }
  737.                    else if((c<'1')||(c>'9')) {
  738.                       putchar('/'); putchar(Ch);
  739.                       Error=INVALIDSWITCH;
  740.                    }
  741.                    else {
  742.                       pos++;
  743.                       if(((c<=(0x30+HDrives))&&(Ch=='H'))||
  744.                          ((c<=(0x30+FDrives))&&(Ch=='F')) ) {
  745.                          Drive=(c-0x31);  if(Ch=='H') Drive|=0x80;
  746.                       }
  747.                    }
  748.                    if (Drive!=i) ReadRoot=1;
  749.                    break;
  750.  
  751.          case 'W':
  752.             if ((Ch=CmdStr[++pos])=='+') {
  753.                OverWrite=1;
  754.                pos++;
  755.             }
  756.             else OverWrite=0;
  757.             if(GetFileName()==0) {
  758.                if(ReadPTable()==0) {
  759.                   OHandle=0;
  760.                   if(OverWrite==0) {
  761.                      OHandle=FOpen(FlName,0);
  762.                      if (OHandle!=0) {
  763.                         FClose(OHandle);
  764.                         putstring(SkipExisting); putstring(File);
  765.                         putstring(FlName); newline();
  766.                      }
  767.                   }
  768.                   if(OHandle==0) {
  769.                      OHandle=FCreate(FlName,0);
  770.                      if (OHandle==0) putDOSError(CREATING,FlName);
  771.                      else
  772.                         if(FWrite(OHandle,(byte far *)RootSect,RW_size,&i)){
  773.                            ExitError|=EE_ERRORINWRITING;
  774.                            if(DOSFileError==0) {
  775.                               putstring(MaybeDiskFull);
  776.                               putstring(File); putstring(FlName); newline();
  777.                            }
  778.                            else putDOSError(WRITING,FlName);
  779.                         }
  780.                      if(FClose(OHandle)) putDOSError(CLOSING,FlName);
  781.                   }
  782.                }
  783.             }
  784.             break;
  785.          default:
  786.             putchar('/');
  787.             Error=INVALIDSWITCH;
  788.          }
  789.       }
  790.       else {
  791.          if(GetFileName()==0) {
  792.             if (IHandle==0) {
  793.                IHandle=FOpen(FlName,0);
  794.                if (IHandle==0) putDOSError(OPENING,FlName);
  795.                else {
  796.                   Opened[0]=0;
  797.                   stradd(Opened,FlName);
  798.                }
  799.             }
  800.          }
  801.       }
  802.       if (ReadRoot==2) {
  803.          if(IHandle!=0) FClose(IHandle);
  804.          Error=ROOTUNREADABLE;
  805.       }
  806.       else if (Error<0) {
  807.          if(Error!=INVALIDSWITCH) putstring(FlName);
  808.          if(CmdStr[pos]!=CR) putchar(CmdStr[pos]);
  809.          putstring(ErrMess[-Error-1]);
  810.          if(IHandle!=0) FClose(IHandle);
  811.       }
  812.       else SkipBlanks();
  813.    }
  814.    if((Error==0)&&(IHandle!=0)) {
  815.       i=RW_size;
  816.       if(BootToo && (Drive & 0x80)) RW_size=1024;  else RW_size=512;
  817.       if(i!=RW_size) ReadRoot=1;
  818.       if(FRead(IHandle,(char far *) Buffer,RW_size,&i)){
  819.          if((i==512)&&(BootToo)&&(!BootPartition(Buffer))) {
  820.             BootToo=0;
  821.             ExitError|=EE_BOOTNOTCHECKED;
  822.          }
  823.          else {
  824.             ExitError|=EE_ERRORINREADING | EE_NOTCHECKED;
  825.             if(DOSFileError==0) {
  826.                putstring(NotGoodFile); putstring(File);
  827.                putstring(Opened); newline();
  828.             }
  829.             else putDOSError(READING,Opened);
  830.          }
  831.       }
  832.       if(FClose(IHandle)) putDOSError(CLOSING,Opened);
  833.       if((ExitError & EE_ERRORINREADING)==0) {
  834.          /* Confronting message */
  835.            putstring("Confronting root ");
  836.               if(BootToo) putstring ("and boot ");
  837.            putstring("sector with"); putstring(File);
  838.            putchar('['); putstring(Opened); putchar(']');
  839.            /* putchar('('); puthexword(IHandle); putchar(')'); */
  840.            newline();
  841.          /* ******************* */
  842.          if((ReadPTable()==0)||(ReadRoot==3)) {
  843.             Ch=0;
  844.             for (i=0; i<RW_size; i++)
  845.                if (RootSect[i]!=Buffer[i]) { Ch=1; break; }
  846.             if(Ch==1) {
  847.                if(i<512) putchar('R'); else putchar('B');
  848.                putstring(NotEquals);
  849.                if(AutoCorrect) {
  850.                   if(!WritePTable()) ExitError|=EE_CORRECTED;
  851.                }
  852.                if(StopOnError) {
  853.                  putchar('\7'); putchar('\7');
  854.                  while (1);
  855.                }
  856.             }
  857.          }
  858.       }
  859.    }
  860.    else ExitError|=EE_NOTCHECKED;
  861.    return ExitError;
  862. /* } */
  863. #if 0
  864.    for (i=0; i<200; i++) {
  865.       putchar(((byte far *) (_ReadRootSector /* FOpen */))[i]);
  866.    }
  867. #endif
  868. }